/**
 * QUANSHI.com Inc.
 * Copyright (c) 2016-2017 All Rights Reserved.
 */
package com.quanshi.scheduler.core.rpc.netcom.jetty;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;

import com.quanshi.scheduler.core.rpc.codec.RpcRequest;
import com.quanshi.scheduler.core.rpc.codec.RpcResponse;
import com.quanshi.scheduler.core.rpc.netcom.jetty.client.JettyClient;

/**
 * NetComClientProxy
 * 
 * @author chinaxiang
 * @version 2017年7月7日 下午10:08:17
 */
public class NetComClientProxy implements FactoryBean<Object> {

    private static final Logger logger = LoggerFactory.getLogger(NetComClientProxy.class);

    private Class<?>            iface;
    String                      serverAddress;
    JettyClient                 client = new JettyClient();

    public NetComClientProxy(Class<?> iface, String serverAddress) {
        this.iface = iface;
        this.serverAddress = serverAddress;
    }

    @Override
    public Object getObject() throws Exception {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { iface }, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                // request
                RpcRequest request = new RpcRequest();
                request.setServerAddress(serverAddress);
                request.setCreateMillisTime(System.currentTimeMillis());
                request.setClassName(method.getDeclaringClass().getName());
                request.setMethodName(method.getName());
                request.setParameterTypes(method.getParameterTypes());
                request.setParameters(args);

                // send
                RpcResponse response = client.send(request);

                // valid response
                if (response == null) {
                    logger.error("rpc netty response not found.");
                    throw new Exception("rpc netty response not found.");
                }
                if (response.isError()) {
                    throw new RuntimeException(response.getError());
                } else {
                    return response.getResult();
                }

            }
        });
    }

    @Override
    public Class<?> getObjectType() {
        return iface;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

}
